45. Maven - Maven 用法和集成 SSM

安装

下载/添加环境变量

下载地址 https://maven.apache.org/download.cgi。 历史版本地址 https://archive.apache.org/dist/maven/maven-3/

Mac 下添加环境变量

1
vim ~/.bash_profile
1
2
export MAVEN_HOME=/Users/rex/Documents/server/apache-maven-3.5.0                
export PATH=$PATH:$MAVEN_HOME/bin

更新环境变量,使其生效

1
source .bash_profile

测试安装

1
mvn -v

优化配置

配置本地仓库地址。在 Maven 目录下新建 RepMaven 文件夹,修改 config 目录下的 settings.xml 文件。

1
<localRepository>/Users/rex/Documents/server/apache-maven-3.5.0/RepMaven</localRepository>

配置远程仓库地址,复制下面内容到 mirrors 标签中。

1
2
3
4
5
6
 <mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

指定 JDK 版本为 1.8,复制下面内容到 profiles 标签中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<profile>
<id>jdk-1.8</id>

<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

常用命令

注意⚠️:运行Maven命令时一定要进入pom.xml文件所在的目录!命令可以组合使用,例如 mvn clean compile, 即先 clean,再编译。

创建如下工程目录文件,在 pom.xml 路径下执行下面命令 代码地址

编译业务源代码

1
mvn compile

编译 src/main 目录下的类,将编译结果放入项目根目录下 target 下 classes 中

编译测试源代码

1
mvn test-compile

编译 src/test 目录下的类,将编译结果放入项目根目录下 target 下 test-classes 中

清理编译内容

1
mvn clean

会直接将 target 目录删除

测试

1
mnv test

执行 test 目录下面的单元测试

将编译后的源码打包

1
mnv package

mnv package 会执行一系列命令,包括编译,运行测试等。打出来的 jar 包是编译后的。

打源码包

1
mvn source:jar

直接将源码打包,而不是编译后的代码。

将自定义的maven项目, 安装至本地仓库

那么如果我们是内部项目,自定义的构建并不公开至网络上,项目成员又想依赖他怎么办呢?我们可以使用 mvn install 来将一个自定义的 maven 项目, 安装至本地仓库

1
mvn install

pom 文件解读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<!-- 坐标 -->
<groupId>com.atguigu.maven</groupId> <!-- 组织ID -->
<artifactId>Hello</artifactId> <!-- 模块名称 -->
<version>0.0.1-SNAPSHOT</version> <!-- 版本号 -->

<!-- 项目名字 -->
<name>Hello</name>

<!-- 依赖 -->
<dependencies>
<dependency>
<!-- 坐标 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<!-- 依赖的范围 -->
<scope>test</scope>
</dependency>
</dependencies>
</project>

搜索 Maven 依赖包

我们可以到 http://mvnrepository.com/ 搜索需要的jar包的依赖信息。

例如我们在 pom 中新增 mysql 依赖,在 mvnrepository 中找到 mysql 依赖后 https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.6 ,直接添加进入 pom 文件中。

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

然后进行 mvn compile 编译,这样就能将所缺的 mysql jar 包下载下来,再次查看 Maven 本地仓库即可看到。

STS 中使用 Maven

配置 Maven 工作空间

创建 Maven 项目

上图中的 Packagin 用于指定创建的项目的工程类型,jar 表示创建的是一个 java 工程(默认)。pom 表示用于创建父工程,war 用于声明 web 工程。

STS 中执行 Maven 命令

如果没有想要的命令,还可以执行自定义命令

依赖的范围

1
2
3
4
5
6
7
8
<dependency>
<!—坐标 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<!-- 依赖的范围 -->
<scope>test</scope>
</dependency>

当一个 Maven 工程添加了对某个 jar 包的依赖后,这个被依赖的 jar 包可以对应下面几个可选的范围:

compile

  1. main目录下的Java代码可以访问这个范围的依赖
  2. test目录下的Java代码可以访问这个范围的依赖
  3. 部署到Tomcat服务器上运行时放在WEB-INF的lib目录下

不加 scope,默认就是 compile

test

  1. main目录下的Java代码不能访问这个范围的依赖

  2. test目录下的Java代码可以访问这个范围的依赖

  3. 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下

例如:对junit的依赖。仅仅是测试程序部分需要。

provided

  1. main目录下的Java代码可以访问这个范围的依赖

  2. test目录下的Java代码可以访问这个范围的依赖

  3. 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下

例如:servlet-api在服务器上运行时,Servlet容器会提供相关API,所以部署的时候不需要。

main目录下的Java代码能否访问 test目录下的Java代码能否访问 部署时WEB-INF的lib目录下是否存在
compile
test
provided

依赖的传递性

当存在间接依赖的情况时,主工程对间接依赖的jar可以访问吗?这要看间接依赖的jar包引入时的依赖范围——只有依赖范围为compile时可以访问。例如:

传递的规则:

创建 web 工程

代码地址

Packaging 选择 war 类型。此时创建出来的 web 项目是没有 web.xml 文件和 WEB-INF 等目录的,我们需要从其他地方拷贝过来,或者让其生成。下面演示怎么自动生成

这样操作之后,在 src/main/webapp 下面就会自动生成 WEB-INF,web.xml 等文件了。但是这时,我们创建一个 jsp 文件,发现报错,而且在 jsp 中写内容没有提示,因为之前的项目我们都是以 tomcat 方式运行的,tomcat 里面包含了 jsp-api 和 servlet-api,而通过 maven 方式创建的项目就没有。所以我们还需要引入 jsp-api 和 servlet-api 这两个依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
</dependencies>

这样就能解决 jsp 报错和没有提示的问题了。

继承

父工程

创建父工程和创建一般的Java工程操作一致,唯一需要注意的是:打包方式处要设置为pom。下方红色部分需要设置为 pom,这样创建的才是父工程。

子工程中引用父工程

父工程

1
2
3
4
5
6
7
<parent>
<!-- 父工程坐标 -->
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<relativePath>从当前目录到父项目的pom.xml文件的相对路径</relativePath>
</parent>

子工程

1
2
3
4
5
6
7
8
<parent>
<groupId>com.atguigu.maven</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>

<!-- 指定从当前子工程的pom.xml文件出发,查找父工程的pom.xml的路径 -->
<relativePath>../Parent/pom.xml</relativePath>
</parent>

此时如果子工程的groupId和version如果和父工程重复则可以删除。

父工程中管理依赖

将Parent项目中的dependencies标签,用dependencyManagement标签括起来

1
2
3
4
5
6
7
8
9
10
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

在子项目中重新指定需要的依赖,删除范围和版本号。这样的好处就是父工程统一管理了所有的依赖,子依赖用到什么就重新指定什么。

1
2
3
4
5
6
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>

聚合

将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行clean操作。而使用了聚合之后就可以批量进行Maven工程的安装、清理工作。

在总的聚合工程中使用modules/module标签组合,指定模块工程的相对路径即可

1
2
3
4
5
<modules>
<module>../Hello</module>
<module>../HelloFriend</module>
<module>../MakeFriends</module>
</modules>

搭建项目

这里搭建 zcw 项目,项目可以分为以下几个工程。

  1. parent 父工程,聚合其他工程(pom)
  2. main Web工程,存放所有页面,框架配置文件(war)
  3. impl 后台管理系统,存放控制器类,业务层实现类(jar) ,Dao映射文件
  4. api 后台管理系统,存放业务层接口和DAO层接口(jar)
  5. common 存放所有模块所需要的公共类(jar)
  6. bean 存放所有模块的实体类(jar)

因为 parent 是父工程,所有其他工程都需要继承 parent。而且每个工程之间有依赖,如下图所示,web 依赖 impl,impl 依赖 api 和 conmon,api 依赖 bean。所以还需要在 xml 中配置 dependency 所依赖的项目。

我们可以通过 sts 自带的通行界面来快速配置父工程和所依赖的工程。

在 main 中配置 mybatis,spring-mvc,spring 等。最后使用 mbg 插件生成实体 bean 和 mapper 抽象类和 mapper.xml 文件。这里借助的是 mbg 的 maven 插件,在 main 的 pom 文件中进行如下配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- mbg 逆向插件, 运行  mvn mybatis-generator:generate 就能逆向生成 bean 和抽象 mapper 信息 -->
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

代码地址